// TODO
// impulsive force
// rotation bug
// easing factor
// idle mode
// card drawing sequence randomly 

import oscP5.*;
import netP5.*;

TUIOzoneCollection zones;

// images
PImage back, frame, shadow;
PImage [][][] images	= new PImage [5][10][2];
String [] group = new String[5];
int [] imgLen = new int[5];

// motion
ArrayList idMapping ;
int [] transition = new int[5]; //	0: no 1: disk centering 
boolean [] state = new boolean [5];  	//		0: inactive 1: active
int [][] randomPosition = new int[10][2];
ArrayList frontImages = new ArrayList();


// const
 float EASING = 0.5;

void setup() {
	size(1024,768);
	// size(screen.width,screen.height);
	smooth();
	noStroke();
	
	// zone declare
	zones=new TUIOzoneCollection(this);

	// image&zone setting
	setImgAndZone();
	
	// id mapping init
	idMapping = new ArrayList();
	for (int i = 0; i < 5; i++){
		idMapping.add(i);	
		
		transition[i] = 0; 	// transition state init
		state[i] = false;
		
	}
	
	// background images
	back = loadImage("background.jpg");
	frame = loadImage("frame.png");
	shadow = loadImage("shadow.png");
	
}

void update() {

	// centering
	for (int i = 0; i < 5; i++){
		if (transition[i] == 1){
			makeCenter(i);
		} else if (transition[i] == 2){
			makeExplode(i);
		}
	}
}


void drawImgBack(String name, int i, float rot){
	int x = zones.getZoneX(name);
	int y = zones.getZoneY(name);
	float w = zones.getZoneWidth(name);
	float h = zones.getZoneHeight(name);
	
	// calculate shadow, frame position 
	float fw = (w-50)*(1064-56)/(1024-50)+56;
	float d = (fw-w)/2;
	float fh = h + d*2;	
	float sdx = d * (18.0/20);
	float sdy = d * (22.0/20);
	
	pushMatrix();
	translate(x-d+sdx+fw/2, y-d+sdy+fh/2);
	rotate(rot);
	image(shadow, -fw/2, -fh/2, fw, fh);	
	popMatrix();
	
	pushMatrix();
	translate(x -d + fw/2, y-d+fh/2);
	rotate(rot);

	rect(-fw/2, -fh/2, fw, fh);
	//image(frame, -fw/2, -fh/2, fw, fh);	
	popMatrix();
	
}

void draw() {
	//println(frameRate);
	background(0);
	image(back, 0, 0);
	
	// update motions
	update();
	
	// draw images 
	for (int i = 0; i < zones.tzone.length; i++) {
		String name = zones.tzone[i].name;
		String [] splited = split(name, '_');
		for (int j =0; j < group.length; j++){

			if ((splited[0]+"_").equals(group[j])){
				int indexInGroup = Integer.parseInt(splited[1])-1;
				
				int x = zones.getZoneCenterX(name);
				int y = zones.getZoneCenterY(name);
				float w = zones.getZoneWidth(name);
				float h = zones.getZoneHeight(name);
				float rot = zones.getGestureRotation(name);
				
				drawImgBack(name, i, rot);
			
				pushMatrix();
				translate(x, y);
				rotate(rot);
				if (state[j]) { // active or inactive?
					image(images[j][indexInGroup][0], -w/2, -h/2, w, h);
				} else {
					image(images[j][indexInGroup][1], -w/2, -h/2, w, h);
				}
				popMatrix();
				
				break;
			}
		}		
	}
	
	// trick images
	// clicked image is always front
	
	for (int i = 0; i < frontImages.size(); i++){
		String name = "";
		name = (String)frontImages.get(i);
		String [] splited = split(name, '_');
		
		for (int j =0; j < group.length; j++){

			if ((splited[0]+"_").equals(group[j])){
				int indexInGroup = Integer.parseInt(splited[1])-1;
				
				int x = zones.getZoneCenterX(name);
				int y = zones.getZoneCenterY(name);
				float w = zones.getZoneWidth(name);
				float h = zones.getZoneHeight(name);
				float rot = zones.getGestureRotation(name);
				
				drawImgBack(name, i, rot);
				
				pushMatrix();
				translate(x, y);
				rotate(rot);
				if (state[j]) { // active or inactive?
					image(images[j][indexInGroup][0], -w/2, -h/2, w, h);
				} else {
					image(images[j][indexInGroup][1], -w/2, -h/2, w, h);
				}
				popMatrix();
				
				break;
			}
		}		
		
	}
	
	// draw marker
	color(200, 100);
	for (int i = 0; i < 5; i++){
		if(state[i]){
			float x = zones.tobject[i].x*width;
			float y = zones.tobject[i].y*height;
			
			ellipse(x,y, 150, 150);
		}
	}

	// draw cursor
	int [][] cursors = zones.getPoints();
	for (int i = 0; i < cursors.length; i++) {
		ellipse(cursors[i][0], cursors[i][1], 10, 10);
	}
}


void tReleaseEvent(int i){
	//println(i);
	
	for (int j = 0; j < frontImages.size() - i ; j++){
		zones.pullZoneToTop((String)frontImages.get(j));
		print("remove from frontImages: ");
		println((String)frontImages.get(j));

		frontImages.remove(j);
		
	}	
	
}

void clickEvent(String zName){

	if (!zName.equals("canvas"))
		frontImages.add(zName);

}

void objectSetEvent(int nMarker, int nSID){
	print ("set: ");
	print (nSID);
	print(", ");
	println(nMarker);
	idMapping.set(nMarker, nSID);
	
	transition[nMarker] = 1;
	
	state[nMarker] = true;
	
}

void objectOnEvent(int sid){
	print ("On: ");
	println(sid);

	 //int mid = idMapping.indexOf(sid);
	// transition[mid] = 1;
	
}

void objectOffEvent(int sid){
	print ("Off: ");
	println(sid);
	
	 int mid = idMapping.indexOf(sid);
	transition[mid] = 2;
	
	// set random position
	for (int i = 0;i < 10; i++){
		randomPosition[i][0] = int(random(0, width));
		randomPosition[i][1] = int(random(0, height));
	}
	
	// set default size
	float scaleImage = 1.0 / 20.48;				
	float lowerH = int(images[0][0][0].width*scaleImage);
	float lowerW =  int(images[0][0][0].height*scaleImage);
	
	for (int j = 0; j < imgLen[mid]; j++) {
		String name = group[mid]+str(j+1);
		float rand = random(1, 2);
		int w= int(rand*lowerH);
		int h = int(rand*lowerW);
		
		int ix = zones.getZoneX(name);
		int iy = zones.getZoneY(name);
		
		zones.setZoneData0(name, ix, iy, w, h);
	}
		
	
	// inactive setup
	state[mid] = false;
	
	
}

void makeExplode(int i){
	float sum = 0;
	for (int j = 0; j < imgLen[i]; j++) {
		String name = group[i]+str(j+1);
		int ix = zones.getZoneX(name);
		int iy = zones.getZoneY(name);
		int w = zones.getZoneWidth(name);
		int h = zones.getZoneHeight(name);
		
		float a = ((360.0/imgLen[i]) * j)/180*PI;;
		float r = 100.0;
		int mrx = randomPosition[j][0];
		int mry = randomPosition[j][1];
		
		mrx = mrx - w/2;
		mry = mry - h/2;

		ix = int((ix + mrx)*EASING);
		iy = int(( iy + mry)*EASING);
		
		zones.setZoneData0(name, ix, iy, w, h);
		
		sum =+ sqrt((ix-mrx)*(ix-mrx) + (iy-mry)*(iy-mry));
		
		
	}
	
	// check the end of centering
	if (sum < 10) {
		transition[i] = 0;
	}

}

// TODO: alignment
void makeCenter(int i) {
	float x = zones.tobject[i].x;
	float y = zones.tobject[i].y;

	int rx = int(x * width);
	int ry = int(y * height);
	
	float sum = 0;
	for (int j = 0; j < imgLen[i]; j++) {
		String name = group[i]+str(j+1);
		int ix = zones.getZoneX(name);
		int iy = zones.getZoneY(name);
		int w = zones.getZoneWidth(name);
		int h = zones.getZoneHeight(name);
		
		// make front
		zones.pullZoneToTop(name);
		
		// TODO: add random property 
		float a = ((360.0/imgLen[i]) * j)/180*PI;;
		float r = 100.0;
		int mrx = int(rx + r * cos(a));
		int mry = int(ry + r * sin(a));
		mrx = mrx - w/2;
		mry = mry - h/2;

		ix = int((ix + mrx)*EASING);
		iy = int(( iy + mry)*EASING);
		zones.setZoneData0(name, ix, iy, w, h);
		
		sum =+ sqrt((ix-mrx)*(ix-mrx) + (iy-mry)*(iy-mry));
	}
	
	// check the end of centering
	if (sum < 10) {
		transition[i] = 0;
	}

}

void setImgAndZone(){
	// group name setting
	group[0] = "cart_"; 
	imgLen[0] = 5;
	group[1] = "crazy_"; 
	imgLen[1] = 6;
	
	group[2] = "df_"; 
	imgLen[2]= 10;
	group[3] = "ma_"; 
	imgLen[3] = 10;
	group[4] = "mayple_"; 
	imgLen[4]= 6;

	print("image loading");
	for (int i = 0 ; i < group.length; i++) {
		print(".");
		
		for (int j = 0; j < imgLen[i]; j++) {
			
				// load Images
				String name = group[i]+str(j+1);
				images[i][j][0] = loadImage(name+"_color.jpg");
				images[i][j][1] = loadImage(name+"_bw.jpg");

				// init zones
				int randX = int(random(0, width));
				int randY = int(random(0, height));
				
				float scaleImage = 1.0 / 20.48;				
				float lowerW= int(images[i][j][0].width*scaleImage);
				float lowerH =  int(images[i][j][0].height*scaleImage);
				float rand = random(1, 2);
				int w= int(rand*lowerW);
				int h = int(rand*lowerH);
				
				zones.setZone(name, randX, randY, w, h);
				zones.setZoneParameter(name,"DRAGGABLE",true);
				zones.setZoneParameter(name,"THROWABLE",true);
				zones.setZoneParameter(name, "SCALABLE", true);
				
				// scale limit
				zones.setZoneScaleLimits(name, lowerW/w, (lowerH/h)/scaleImage);
				

				
				// default zone is inactive
				zones.setZoneActive(name, false);
		}
	}
	
	// set random rotation
	for (int i = 0; i < zones.tzone.length; i++) {
		zones.tzone[i].gestureRotation = random(0, 2*PI);
	}

}